/**
 * 
 */
package de.fsujena.chat_pi.client;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import de.fsujena.chat_pi.client.userInterface.ConsoleUI;
import de.fsujena.chat_pi.client.userInterface.GraphicalUI;
import de.fsujena.chat_pi.ressources.Room;
import de.fsujena.chat_pi.ressources.User.ROLE;
import de.fsujena.chat_pi.ressources.message.Message;
import de.fsujena.chat_pi.ressources.message.SysMessage;
import de.fsujena.chat_pi.ressources.message.SysMessage.CATEGORY;
import de.fsujena.chat_pi.ressources.message.SysMessage.MESSAGE;
import de.fsujena.chat_pi.ressources.message.TextMessage;

/**
 * @author dave
 *
 */
public class MessageHandler {
	public Client clientObject;
	public ConnectionThread connectionThread;

	/**
	 * @param args
	 */
	public MessageHandler(Client clientObject){
		this.clientObject=clientObject;
		this.connectionThread=clientObject.connectionThread;
	}
	
	public static void main(String[] args) {

	}

	public boolean handle(Message msg){
		
		
		if (msg instanceof TextMessage){						//check if its a textmessage
			TextMessage tempObj= (TextMessage)msg;				//cast into textmessage
			tempObj.setReceived(new Date());					//save the date
			clientObject.UI.postTextMessage(tempObj);	//print the message
			//clientObject.msgArray.add(tempObj);					//save the message
			//clientObject.worker.saveHistory();
			return true;
			}	
		else if (msg instanceof SysMessage) {					//check if its a systemmessage
			
			SysMessage sysMessage = (SysMessage) msg;			//casting
			switch(sysMessage.getCategory()){
			case ERROR:
				error(sysMessage);
				break;
			case REGISTRATION:
				registration(sysMessage);
				break;
			case STATUS:
				status(sysMessage);
				break;
			case LOGIN:
				login(sysMessage);
				break;
			case CONNECTION:
				connection(sysMessage);
				break;
			case CHANGE_USERNAME:
				change_username(sysMessage);
				break;
			case CHANGE_PASSWORD:
				change_password(sysMessage);
				break;
			case ADMIN:
				admin(sysMessage);
				break;
			case MODERATE:
				moderate(sysMessage);
				break;
			case ROOMMANAGEMENT:
				roommanagement(sysMessage);
				break;
			case MISCELLANEOUS:
				miscellaneous(sysMessage);
				break;
			default:
				break;
			}
			return true;		
		}

		
		return false;
	}
	
	

	

	/**
	 * process sysmessages with category error
	 * @param sysMessage message to process
	 */
	public void error(SysMessage sysMessage){
		switch(sysMessage.getMessage()){
		case MSG_NOT_EXPECTED:
			clientObject.UI.postError("message unexpected");
			break;
		case WRONG_MSG_TYPE:
			clientObject.UI.postError("a wrong message was send");
			break;
		case ROOM_DONT_EXISTS:
			clientObject.UI.postError("Room don't exists");
			break;
		case NEED_ADMIN_RIGHTS:
			clientObject.UI.postError("you have to be admin to do this");
			break;
		case NEED_MOD_RIGHTS:
			clientObject.UI.postError("you have to be a moderator to do this");
			break;
		case NEED_NORMAL_RIGHTS:
			clientObject.UI.postError("you can't do this as a guest");
			break;
		default:
		break;
		}
		return;
	}
	/**
	 * process sysmessages with category connection
	 * @param sysMessage message to process
	 */
	public void connection(SysMessage sysMessage){
		switch(sysMessage.getMessage()){
		case CONNECTED:																				//server confirms that the client is connected
			clientObject.UI.postInfo("connected to server "+connectionThread.server.getInetAddress()+" on port:"+connectionThread.server.getPort());	//tell that to the user
			break;
		case DISCONNECTED:																			//a user disconnected
			clientObject.UI.postInfo("["+sysMessage.getMessageString()+"] disconnected");	//tell that to the user
			break;
		case SERVER_CLOSED:
			clientObject.UI.postInfo("server closed");
			break;
		
		default:
		break;
		}
		return;
	}
	/**
	 * process sysmessages with category login
	 * @param sysMessage message to process
	 */
	public void login(SysMessage sysMessage){
		switch(sysMessage.getMessage()){
		case LOGGED_IN:	//server confirms login
			if(clientObject.UI instanceof GraphicalUI){
				clientObject.worker.showHistory();
			}
			clientObject.UI.postInfo("your are now logged in");				//tell the user
			clientObject.worker.loadHistory();
			connectionThread.loggedIn=true;											//flag as logged in
			clientObject.connectionThread.sendSysMessage(CATEGORY.ROOMMANAGEMENT, MESSAGE.REQUEST_ROOM_LIST,clientObject.connectionThread.username);
			//clientObject.connectionThread.sendSysMessage(CATEGORY.ROOMMANAGEMENT, MESSAGE.REQUEST_ROOM_DIR,clientObject.connectionThread.username);
			
			break;
		case NOT_LOGGED_IN:															//user is not logged in
			clientObject.UI.postError("not logged in please log in or register");	//tell that to the user
			connectionThread.loggedIn=false;										//flag as logged out
			break;
		case ALREADY_LOGGED_IN:														//this client is already logged in
			clientObject.UI.postError("you are already logged in");			//tell the user
			break;
		case LOGGED_OUT:															//a user loggeged out
			clientObject.UI.postInfo("["+sysMessage.getMessageString()+"] logged out");//tell the user
			break;
		case USER_ALREADY_LOGGED_IN:												//an other client is already logged in with this name
			clientObject.UI.postError("this user is already logged in please try an other name");	//tell the user
			break;
		case REQUEST_USERNAME:														//server request the username
			connectionThread.sendSysMessage(CATEGORY.LOGIN,MESSAGE.SEND_USERNAME,connectionThread.username);	//send username to the server
			break;
		case USERNAME_UNKNOWN:														//Unknown username
			clientObject.UI.postError("user unknown please register");		//requst an other name
			break;
		case USERNAME_BANNED:
			clientObject.UI.postError("this user is banned from the server");
			break;
		case REQUEST_PASSWORD:														//server request password
			connectionThread.sendSysMessage(CATEGORY.LOGIN,MESSAGE.SEND_PASSWORD,connectionThread.password);	//send the password to the server
			break;
		case PASSWORD_WRONG:														//wrong password
			clientObject.UI.postError("incorrect password please try to login again");	//request a new login
			break;

		
		default:
		break;
		}
		return;
	}
	/**
	 * process sysmessages with category registration
	 * @param sysMessage message to process
	 */
	public void registration(SysMessage sysMessage){
		switch(sysMessage.getMessage()){
		case REQUEST_NEW_USERNAME:												//request new username (after regristration)
			connectionThread.sendSysMessage(CATEGORY.REGISTRATION, MESSAGE.SEND_NEW_USERNAME,connectionThread.username);	//send the new name
			break;
		case USERNAME_ALREADY_EXISTS:											//username already in use (during registration process)
			clientObject.UI.postError("username already in use try an other one");	//tell the user
			break;
		case REQUEST_NEW_PASSWORD:												//request new password (after regristration)
			connectionThread.sendSysMessage(CATEGORY.REGISTRATION, MESSAGE.SEND_NEW_PASSWORD, connectionThread.password);	//send new password
			break;
		case REGISTRATION_SUCCESSFUL:											//server confirms registration
			clientObject.UI.postInfo("Your registration was successful. Please login now using your new username.");	//tell that to the user
			break;
		case TYPE_PASSWORD:
			String tempstr=null;
			tempstr=getPassword();
			clientObject.UI.postInfo("4");
			clientObject.UI.postInfo(tempstr);
			clientObject.UI.postInfo("5");
			connectionThread.sendSysMessage(CATEGORY.LOGIN,MESSAGE.SEND_PASSWORD,tempstr);			//let the user type in the password
			break;
		
		default:
		break;
		}
		return;
	}
	/**
	 * process sysmessages with category change_username
	 * @param sysMessage message to process
	 */
	public void change_username(SysMessage sysMessage){
		switch(sysMessage.getMessage()){
		case REQUEST_CHANGED_USERNAME:													//request new password (after change of password)
			connectionThread.sendSysMessage(CATEGORY.CHANGE_USERNAME, MESSAGE.SEND_CHANGED_USERNAME, connectionThread.newusername);	//send the new password
			break;
		case USERNAME_CHANGED:															//somone has change his username
			if(sysMessage.getSenderUsername().equals("SERVER")){						//if sendername is server this client has changed his name
				clientObject.UI.postInfo("your username was changed to "+sysMessage.getMessageString());	//tell the user
				clientObject.worker.renameHistory(sysMessage.getMessageString());										//rename history file
				connectionThread.username=sysMessage.getMessageString();												//save the new name
				connectionThread.newusername="";																		//reset 
			}else{																										//otherwise an other client changed his name
				clientObject.UI.postInfo(sysMessage.getSenderUsername()+" changed his name to "+sysMessage.getMessageString());	//tell the user
			}
			break;
		case REQUEST_USERNAME:																					//server request the username
			connectionThread.sendSysMessage(CATEGORY.LOGIN,MESSAGE.SEND_USERNAME,connectionThread.username);	//send username to the server
			break;
		case USERNAME_UNKNOWN:																//Unknown username
			clientObject.UI.postError("user unknown please register");				//requst an other name
			break;
		case USERNAME_BANNED:
			clientObject.UI.postError("this user is banned from the server");
			break;
		case REQUEST_PASSWORD:																					//server request password
			connectionThread.sendSysMessage(CATEGORY.LOGIN,MESSAGE.SEND_PASSWORD,connectionThread.password);	//send the password to the server
			break;
		case PASSWORD_WRONG:																	//wrong password
			clientObject.UI.postError("incorrect password please try to login again");	//request a new login
			break;

		
		default:
		break;
		}
		return;
	}
	/**
	 * process sysmessages with category change_password
	 * @param sysMessage message to process
	 */
	public void change_password(SysMessage sysMessage){
		switch(sysMessage.getMessage()){
		case LOGIN_FIRST:
			clientObject.UI.postError("you have to login to do this");
			break;
		case REQUEST_CHANGED_PASSWORD:
			connectionThread.sendSysMessage(CATEGORY.CHANGE_PASSWORD, MESSAGE.SEND_CHANGED_PASSWORD, connectionThread.newpassword);	//send the new password
			break;
		case PASSWORD_CHANGED:
			clientObject.UI.postInfo("your password was changed");
			connectionThread.password=connectionThread.newpassword;
			connectionThread.newpassword="";
			break;
		case REQUEST_USERNAME:																					//server request the username
			connectionThread.sendSysMessage(CATEGORY.LOGIN,MESSAGE.SEND_USERNAME,connectionThread.username);	//send username to the server
			break;
		case USERNAME_UNKNOWN:																//Unknown username
			clientObject.UI.postError("user unknown please register");				//request an other name
			break;
		case USERNAME_BANNED:
			clientObject.UI.postError("this user is banned from the server");
			break;
		case REQUEST_PASSWORD:																					//server request password
			connectionThread.sendSysMessage(CATEGORY.LOGIN,MESSAGE.SEND_PASSWORD,connectionThread.password);	//send the password to the server
			break;
		case PASSWORD_WRONG:																	//wrong password
			clientObject.UI.postError("incorrect password please try to login again");	//request a new login
			break;

		
		default:
		break;
		}
		return;
	}
	/**
	 * process sysmessages with category status
	 * @param sysMessage message to process
	 */
	public void status(SysMessage sysMessage){
		switch(sysMessage.getMessage()){
		case SEND_USER_LIST:																	//server sends the list of user
			if (sysMessage.getMessageObject() instanceof String[]) {
				String[] userList = (String[]) sysMessage.getMessageObject();
				clientObject.UI.postArray("Users currently logged in: %s\n", userList);	//prints list of user
			}
			break;
		case NEW_USER_INFO:																		//info about new user connected
			clientObject.UI.postInfo(sysMessage.getMessageString()+" just connected");	//tell the user
			break;
		case NO_ADMIN:
			clientObject.UI.postError("you need to be a admin to do this");
			break;
		case NO_MOD:
			clientObject.UI.postError("you need to be a moderator to do this");
			break;
		case YOU_ARE_REMOVED:
			clientObject.UI.postError("you are no longer registerd on the server");
			break;
		case SEND_ROOM_LIST:
			if (sysMessage.getMessageObject() instanceof String[]) {
				String[] userList = (String[]) sysMessage.getMessageObject();
				clientObject.UI.postArray("Romm currently available: %s\n", userList);	//prints list of rooms
			}
			break;
		case USER_KICKED:
			clientObject.UI.postInfo("user "+sysMessage.getMessageString()+" was kicked by "+sysMessage.getSenderUsername());
			break;
		case BECOME_ADMIN:
			clientObject.UI.postInfo("["+sysMessage.getMessageString()+"] is now admin");
			break;
		case BECOME_MOD:
			clientObject.UI.postInfo("["+sysMessage.getMessageString()+"] is now moderator");
			break;
		case SEND_ADMIN_LIST:
			if (sysMessage.getMessageObject() instanceof String[]) {
				String[] userList = (String[]) sysMessage.getMessageObject();
				clientObject.UI.postArray("The following users have admin rights: %s\n",userList);	//prints list of admins
			}
			break;
		case SEND_MOD_LIST:
			if (sysMessage.getMessageObject() instanceof String[]) {
				String[] userList = (String[]) sysMessage.getMessageObject();
				clientObject.UI.postArray("The following users have moderator rights: %s\n", userList);	//prints list of admins
			}
			break;
		case SEND_ROLE:
			ROLE role =(ROLE)sysMessage.getMessageObject();
			switch(role){
			case ADMIN:
				clientObject.UI.postInfo("you have admin rights");
				break;
			case MODERATOR:
				clientObject.UI.postInfo("you have moderator rights");
				break;
			case STANDARD:
				clientObject.UI.postInfo("you have standard rights");
				break;
			
			default:
				break;
			}
			
			break;
		case USER_DONT_EXIST:
			clientObject.UI.postError("User "+sysMessage.getMessageString()+" dosn't exist!");
			break;
		default:
		break;
		}
		return;
	}
	/**
	 * process sysmessages with category admin
	 * @param sysMessage message to process
	 */
	public void admin(SysMessage sysMessage){
		switch(sysMessage.getMessage()){
		
		
		default:
		break;
		}
		return;
	}
	/**
	 * process sysmessages with category moderate
	 * @param sysMessage message to process
	 */
	public void moderate(SysMessage sysMessage){
		switch(sysMessage.getMessage()){
		case KICK_USER:
			if(sysMessage.getMessageString().equals(connectionThread.username)) {
				connectionThread.mainThread.isconnected = false;
				clientObject.UI.postInfo("you are kicked by "+sysMessage.getSenderUsername());
			} else clientObject.UI.postInfo("user "+sysMessage.getMessageString()+" was kicked by "+sysMessage.getSenderUsername());
			break;
		case BANN_USER:
			if(sysMessage.getMessageString().equals(connectionThread.username)) {
				connectionThread.mainThread.isconnected = false;
				clientObject.UI.postInfo("you were banned from the server by "+sysMessage.getSenderUsername());
			} else clientObject.UI.postInfo("user "+sysMessage.getMessageString()+" was banned from the server by "+sysMessage.getSenderUsername());
			break;
		case UNBANN_USER:
			if(sysMessage.getMessageString().equals(connectionThread.username))
				clientObject.UI.postInfo("you were unbanned from the server by "+sysMessage.getSenderUsername());
			else clientObject.UI.postInfo("user "+sysMessage.getMessageString()+" was unbanned from the server by "+sysMessage.getSenderUsername());
			break;
		case USER_WARNING:
			clientObject.UI.postWarning("you were warned by "+sysMessage.getSenderUsername()+" for "+(String)sysMessage.getMessageObject());
			break;
	
		
		default:
			
		break;
		}
		return;
	}
	
	
	@SuppressWarnings("unchecked")
	public void roommanagement(SysMessage sysMessage) {
		switch(sysMessage.getMessage()){
		case SEND_ROOM_LIST:
			if(sysMessage.getMessageObject() instanceof Room){
				//clientObject.connectionThread.foyer=((Room)sysMessage.getMessageObject());
				//clientObject.foyer=((Room)sysMessage.getMessageObject());
				clientObject.setFoyer(((Room)sysMessage.getMessageObject()).copyRoom());
				if(clientObject.UI instanceof GraphicalUI){
					((GraphicalUI)clientObject.UI).updateRoomTree(((Room)sysMessage.getMessageObject()).copyRoom());
					sysMessage.setMessageObject(null);
				}
			}else{
				//TODO: Error handling
			}
			break;
		case SEND_ROOM_DIR:
			if(sysMessage.getMessageObject() instanceof List<?>){
				//clientObject.roomDir.clear();
				clientObject.roomDir=(List<String>)sysMessage.getMessageObject();
				/*for(int i=0;i<((List<String>)sysMessage.getMessageObject()).size();i++){
					clientObject.roomDir.add(((List<String>)sysMessage.getMessageObject()).get(i));
				}
					*/
				String temp ="";
				
				for(int i=0;i<clientObject.roomDir.size();i++){
					temp=temp+clientObject.roomDir.get(i)+"/";
					
				}
				clientObject.UI.postInfo("your are in "+temp);
			}else{
				//TODO:error handling
			}
			
			break;
		case ENTER_ROOM:
			if(sysMessage.getMessageString().equals(clientObject.connectionThread.username)){
			if(sysMessage.getMessageObject() instanceof Room){
				clientObject.room=(Room)sysMessage.getMessageObject();
				clientObject.roomDir=clientObject.room.getDir();
				clientObject.UI.postInfo("You entered "+clientObject.room.getName());
				
			}else{
				//TODO error handling
			}}else{
				clientObject.UI.postInfo(sysMessage.getMessageString()+" entered "+((Room)sysMessage.getMessageObject()).getName());
			}
			break;
		case ROOM_WAS_CREATED:
			if(sysMessage.getMessageObject() instanceof Room){
			clientObject.UI.postInfo("Room "+((Room)sysMessage.getMessageObject()).getName()+" was created by "+sysMessage.getMessageString());
			}else{
				//TODO error handling
			}
			break;
		case ROOM_REMOVED:
			if(sysMessage.getMessageObject() instanceof Room){
			clientObject.UI.postInfo("Room "+((Room)sysMessage.getMessageObject()).getName()+" was removed by "+sysMessage.getMessageString());
			}else{
				//TODO error handling
			}
			break;
		case CREATE_ROOM:
			
			if(sysMessage.getMessageObject() instanceof List<?>){
				List<String> tempdir=(List<String>)sysMessage.getMessageObject();
				String temp=null;
				for(int i=0;i<tempdir.size();i++){
					temp=temp+tempdir.get(i)+"/";
					
				}
				if(sysMessage.getMessageString().equals(clientObject.connectionThread.username)){
					
					clientObject.UI.postInfo("you created the room "+temp);
				}else{
					clientObject.UI.postInfo(sysMessage.getMessageString()+" created the room "+temp);
				}
			}else{
				//TODO error handling
			}
			break;
		case AVAILABLE_ROOMS:
			if(sysMessage.getMessageObject() instanceof List<?>){
				List<String> templist=(List<String>)sysMessage.getMessageObject();
				clientObject.UI.postInfo("Rooms available:");
				for(int i=0;i<templist.size();i++){
					clientObject.UI.postInfo(templist.get(i));
				}
			}else{
				//TODO error handling
			}
			break;
		case ROOM_IS_PRIVATE:
			clientObject.UI.postError("This room is private! (owend by "+sysMessage.getMessageString()+" )");
			break;
		case NOT_ALLOWED_IN_THIS_ROOM:
			clientObject.UI.postError("you are blacklisted in this room!");
			break;
		case ERROR_CREATING_ROOM:
			clientObject.UI.postError("an error ocured while creating the room!");
			break;
		case SEND_WHITELIST:
			if (sysMessage.getMessageObject() instanceof String[]) {
				String[] whiteList = (String[]) sysMessage.getMessageObject();
				clientObject.UI.postArray("user allowed in this room: %s\n", whiteList);	//prints list of rooms
			}
			break;
		case SEND_BLACKLIST:
			if (sysMessage.getMessageObject() instanceof String[]) {
				String[] blackList = (String[]) sysMessage.getMessageObject();
				clientObject.UI.postArray("user allowed in this room: %s\n", blackList);	//prints list of rooms
			}
			break;
		case COULDNT_MAKE_PRIVATE:
			clientObject.UI.postError("couldn't make the room private");
			break;
		case WANT_ON_WHITELIST:
			
			if(clientObject.UI instanceof ConsoleUI){
				clientObject.worker.want_on_whitelist=true;
				clientObject.worker.want_on_whitelist_name=sysMessage.getMessageString();
				clientObject.worker.want_on_whitelist_dir=(List<String>)sysMessage.getMessageObject();
				String temp="";
				for(int i=0;i<clientObject.worker.want_on_whitelist_dir.size();i++){
					temp=temp+clientObject.worker.want_on_whitelist_dir.get(i)+"/";
				}
				clientObject.UI.postInfo("allow user "+sysMessage.getMessageString()+" to enter room "+temp+" ?");
			}else{
				clientObject.worker.want_on_whitelist=true;
				clientObject.worker.want_on_whitelist_name=sysMessage.getMessageString();
				clientObject.worker.want_on_whitelist_dir=(List<String>)sysMessage.getMessageObject();
				((GraphicalUI)clientObject.UI).want_on_whitelist();
				
			}
			break;
		case WANT_ON_WHITELIST_ACCEPTED:
			if(sysMessage.getMessageObject() instanceof List<?>){
			String temp="";
			List<String> tempdir=(List<String>)sysMessage.getMessageObject();
			for(int i=0;i<tempdir.size();i++){
				temp=temp+tempdir.get(i)+"/";
			}
			
			clientObject.UI.postInfo("you can now enter room "+temp);
			}
			break;
		case WANT_ON_WHITELIST_DENIED:
			if(sysMessage.getMessageObject() instanceof List<?>){
			String temp="";
			List<String> tempdir=(List<String>)sysMessage.getMessageObject();
			for(int i=0;i<tempdir.size();i++){
				temp=temp+tempdir.get(i)+"/";
			}
			
			clientObject.UI.postInfo("your request to enter "+temp+" was denied");
			}
			break;
		case WANT_ON_WHITELIST_REQUESTED:
			clientObject.UI.postError("you are not allowed to enter this room an request for permission was sent");
			break;
		default:
			
		break;
		}
		return;
	}
	
	private void miscellaneous(SysMessage sysMessage) {
		// TODO Auto-generated method stub
		switch(sysMessage.getMessage()){
		case WHISPER:
		if (sysMessage.getMessageObject() instanceof String){
			clientObject.UI.postInfo(sysMessage.getSenderUsername()+" is whispering: "+(String)sysMessage.getMessageObject());
		}
			
			break;
		default:
			break;
		}
		
	}
	
	/**
	 * aks the user about the password
	 * @param newuser flag if a new user
	 * @return	string containing the password
	 */
	public String getPassword() {
	//TODO find out why the hell this doesn't work (hint readline doesn't work)
		clientObject.UI.postInfo("Enter Password:");		//ask for the password
		String passwd=null;
		try {
			clientObject.UI.postInfo("1");
			//if (console != null) {								//only if there actually is a console (there is no console in eclipse)
				//passwd = new String(console.readPassword());	//read password from console with masked characters
				//return passwd;
		//	} else {
				passwd= clientObject.input.readLine();						//without console read as standard input
				
				clientObject.UI.postInfo("2");
				return passwd;
				
			//}
			
		} catch (Exception e) {
			e.printStackTrace();
			return "bob";
		}

	}
	
}
